
/*
* @Author: zhangq
* @Date: 2022-04-06 
* @LastEditTime: 2022-4-6
* @LastEditors: zhanggq
* @Description: dlt645帧定义、控制码定义
* @FilePath: src\dlt645\include\dlt645def.h
*/

#ifndef __DLT645_DEF__
#define __DLT645_DEF__
#include <iostream>
#include <memory>
#include <string.h>
#include <list>

#define   CHR_PREFIX		0xFE	//前导符
#define   CHR_FRMSTART		0x68	//帧起始符
#define   CHR_FRMEND		0x16	//帧结束符
#define   FLAG_ERRIDENT		0x33	//差错控制标识

#define   MIN_FRAME_LEN     12     //最小帧长度

//DL645-2007 控制码
typedef enum  _dl645CtrlCode
{
    ENUM_CTRLCODE_SAFETY_CERTIF         = 0x03,     //安全认证
    ENUM_CTRLCODE_BROADCAST_TIMING      = 0x08,		//广播校时-------无应答
    ENUM_CTRLCODE_READ_METERDATA        = 0x11,		//读电能表数据
    ENUM_CTRLCODE_READ_SUBSEQDATA       = 0x12,		//读后续数据
    ENUM_CTRLCODE_READ_COMMADR          = 0x13,		//读通信地址---仅支持点对点通信
    ENUM_CTRLCODE_WRITE_DATA            = 0x14,		//主站向从站写数据
    ENUM_CTRLCODE_WRITE_COMMADDR        = 0x15,		//主站向从站写通信地址--仅支持点对点通信
    ENUM_CTRLCODE_FREEZE_METERDATA      = 0x16,		//冻结表数据
    ENUM_CTRLCODE_CHANGE_COMMRATE       = 0x17,		//更改电能表通信速率
    ENUM_CTRLCODE_MODIFY_PASSWORD       = 0x18,     //修改密码
    ENUM_CTRLCODE_MAXDEMAND_CLEAR       = 0x19,		//最大需量清零
    ENUM_CTRLCODE_DATA_CLEAR            = 0x1A,		//电表数据清零
    ENUM_CTRLCODE_EVENT_CLEAR           = 0x1B,		//事件清零
    ENUM_CTRLCODE_TRIPCLOSING_ALERT     = 0x1C,     //跳合闸、报警、保电
    ENUM_CTRLCODE_TERMINAL_CTRL         = 0x1D,		//多功能端子输出控制命令
    ENUM_CTRLCODE_TRANSMIT_DATA         = 0x1E      //转发数据
}ENUM_DL645_CTRLCODE;


//DL645-2007应答码
typedef enum _dl645RspCode
{
    ENUM_CTRLCODE_RSP_NONE                          = 0,        //初始化使用
    ENUM_CTRLCODE_SAFETY_CERTIF_RSP                 = 0x83,		//安全认证正常应答码
    ENUM_CTRLCODE_READ_METERDATA_RSP                = 0x91,		//读电能表数据正常应答码
    ENUM_CTRLCODE_READ_SUBSEQDATA_RSP               = 0x92,		//读后续数据且无后续数据正常应答码

    ENUM_CTRLCODE_READ_COMMADR_RSP                  = 0x93,		//读通信地址
    ENUM_CTRLCODE_WRITE_DATA_RSP                    = 0x94,		//主站向从站写数据正常应答码
    ENUM_CTRLCODE_WRITE_COMMADDR_RSP                = 0x95,		//主站向从站写通信地址--正常应答码
    ENUM_CTRLCODE_FREEZE_METERDATA_RSP              = 0x96,		//冻结表数据正常应答码
    ENUM_CTRLCODE_CHANGE_COMMRATE_RSP               = 0x97,		//更改电能表通信速率正常应答码
    ENUM_CTRLCODE_MODIFY_PASSWORD_RSP               = 0x98,     //修改密码正常应答码
    ENUM_CTRLCODE_MAXDEMAND_CLEAR_RSP               = 0x99,		//最大需量清零正常应答码
    ENUM_CTRLCODE_DATA_CLEAR_RSP                    = 0x9A,		//电表数据清零正常应答码
    ENUM_CTRLCODE_EVENT_CLEAR_RSP                   = 0x9B,		//事件清零正常应答码
    ENUM_CTRLCODE_TRIPCLOSING_ALERT_RSP             = 0x9C,		//跳合闸、报警、保电正常应答码
    ENUM_CTRLCODE_TERMINAL_CTRL_RSP                 = 0x9D,		//多功能端子输出控制命令正常应答码
    ENUM_CTRLCODE_TRANSMIT_DATA_RSP                 = 0x9E,     //数据转发正常应答码

    ENUM_CTRLCODE_READ_METERDATA_HAVESUBSEQ_RSP     = 0xB1,     //读电能表数据正常且有后续数据应答码
    ENUM_CTRLCODE_READ_SUBSEQDATA_HAVESUBSEQ_RSP    = 0xB2		//读后续数据正常且有后续数据应答码
}ENUM_DL645_RSPCODE;

//DL645-2007异常码
typedef enum _dl645AbnormalCode
{
    ENUM_CTRLCODE_SAFETY_CERTIF_ABNORMAL        = 0xC3,		//安全认证异常应答码
    ENUM_CTRLCODE_READ_METERDATA_ABNORMAL       = 0xD1,		//读电能表数据异常应答码
    ENUM_CTRLCODE_READ_SUBSEQDATA_ABNORMAL      = 0xD2,		//读后续数据异常应答码
    ENUM_CTRLCODE_WRITE_DATA_ABNORMAL           = 0xD4,		//主站向从站写数据异常应答码
    ENUM_CTRLCODE_FREEZE_METERDATA_ABNORMAL     = 0xD6,		//冻结表数据异常应答码
    ENUM_CTRLCODE_CHANGE_COMMRATE_ABNORMAL      = 0xD7,		//更改电能表通信速率异常应答码
    ENUM_CTRLCODE_MAXDEMAND_CLEAR_ABNORMAL      = 0xD9,		//最大需量清零异常应答码
    ENUM_CTRLCODE_DATA_CLEAR_ABNORMAL           = 0xDA,		//电表数据清零异常应答码
    ENUM_CTRLCODE_EVENT_CLEAR_ABNORMAL          = 0xDB,		//事件清零异常应答码
    ENUM_CTRLCODE_TRIPCLOSING_ALERT_ABNORMAL    = 0xDC,	    //跳合闸、报警、保电异常应答码
    ENUM_CTRLCODE_TERMINAL_CTRL_ABNORMAL        = 0xDD		//多功能端子输出控制命令异常应答码
}ENUM_DL645_ABNORMALCODE;

//DLT645数据类型
typedef enum __dlt645_datatype
{
    ENUM_645_DATATYPE_CHAR              = 260,    //有符号字节
    ENUM_645_DATATYPE_UNSIGNED_CHAR     = 261,    //无符号字节
    ENUM_645_DATATYPE_SHORT             = 262,    //有符号短整数型（2个字节）
    ENUM_645_DATATYPE_UNSIGNED_SHORT    = 263,    //无符号短整数型（2个字节）
    ENUM_645_DATATYPE_INT               = 264,    //有符号整数型（4个字节）
    ENUM_645_DATATYPE_UNSIGNED_INT      = 265,    //无符号整数型（4个字节）
    ENUM_645_DATATYPE_INT64             = 266,    //有符号64位整数型(8个字节)
    ENUM_645_DATATYPE_UNSIGNED_INT64    = 267,    //有符号64位整数型(8个字节)
    ENUM_645_DATATYPE_FLOAT             = 268,    //浮点型(4个字节)
    ENUM_645_DATATYPE_DOUBLE            = 269,   //双精度型(8个字节)
    ENUM_645_DATATYPE_STRING            = 270,   //字符串型(变长)
    ENUM_645_DATATYPE_DATETIME          = 25     //日期时间型
}ENUM_DLT645_DATATYPE;

typedef enum __dlt645_hex_order{
    ENUM_645HEX_ORDER_LITTLE_ENDIAN  =0,
    ENUM_546HEX_ORDER_BIG_ENDIAN     =1
}ENUM_645HEX_BYTEORDER;

/**
* @brief 645字节序
*
*/
typedef enum  _dlt645_encodetype{
    ENUM_645_ENCODE_BCD = 0,
    ENUM_645_ENCODE_HEX = 1
}ENUM_DLT645_ENCODE_TYPE;
/**
* @brief 645字节序
*
*/
typedef enum _dlt645_isalarm{
    ENUM_645_NOALARM = 0,
    ENUM_645_ISALARM = 1
}ENUM_645_DO_ALARM;

/**
* @brief 采集数据使用的数据结构
*
*/
typedef struct _dl645_rspData{
    int64_t             dev_id;             //设备id
    int64_t             protocol_id;        //规则id
    uint8_t         meter_addr[6];      //表地址
    std::string     di;                 //数据标识
    int         data_type_id;           //数据类型id，与t_data_type的code对应
    int         datalen;                //数据长度
    uint8_t     *pdata;                 //数据内容
    _dl645_rspData(){
        dev_id = 0;
        protocol_id = 0;
        memset(meter_addr, 0, 6);        
        data_type_id = -1;
        datalen = 0;
        pdata = nullptr;
    }
}ST_DL645_RSPDATA;

//帧格式
typedef  struct _dl645_frame
{
    //前导符
    uint8_t  ucPrefix[4] = { 0xfe, 0xfe, 0xfe, 0xfe };
    //帧起始码
    uint8_t   ucStartCode1;
    //地址码
    uint8_t   ucAddrCode[6];
    //帧起始码
    uint8_t   ucStartCode2;
    //控制码
    ENUM_DL645_CTRLCODE  enCtrlCode;
    //数据域长度
    uint8_t  ucDataLen;
    //数据域
    uint8_t*    pData;
    //校验码
    uint8_t  ucCS;
    //帧结束符
    uint8_t  ucEndCode;
}ST_DL645_FRAME;

//写数据、设备控制帧参数
typedef struct __writedata_item
{
    uint8_t ctrlcode;
    uint8_t szMeterAddr[6];
    uint8_t szDataFlag[4];
    uint8_t szPasswd[4];
    uint8_t szOprCode[4];
    uint8_t frmData[32];
    uint8_t datalen;
    uint8_t oprcode_len;    //有的帧没有操作者代码，通过此长度判断
    uint8_t pwd_len;        //密码长度
    __writedata_item(){
        ctrlcode = 0;
        memset(szMeterAddr,0,6);
        memset(szDataFlag, 0, 4);
        memset(szPasswd, 0, 4);
        memset(szOprCode, 0, 4);
        memset(frmData, 0, 32);
        datalen = 0;
        oprcode_len = 0;
        pwd_len = 0;
    }
}st_dlt645_wrtdata_items;

//----------------------------------------------------------------------------------
//冻结数据项类型
typedef enum   _enum_frozenitem_type
{
    ENUM_FROZEN_TYPE_NONE       = 0,
    ENUM_FROZEN_TYPE_TIME       = 1, //冻结时间
    ENUM_FROZEN_TYPE_DATA       = 2, //冻结数据项
    ENUM_FROZEN_TYPE_LOADREC    = 3, //负荷记录
    ENUM_FROZEN_TYPE_LOADREC_T  = 4  //负荷记录+时间
}ENUM_FROZENITEM_TYPE;

//冻结数据抄读参数
typedef struct FrozenTask_Param{
    int64_t  dev_id;			//设备ID
    int64_t  protocol_id;		//协议规则ID
    std::string     frozen_type;            //冻结数据类型
    std::string     frozen_time_di; 		//冻结时间DI
    std::list<std::string>  lstdata_di;		//冻结数据DI列表
}st_dlt645_frozen_param;
//负荷记录抄读块
typedef struct _loadrec_block_
{
    int          block_count;   //块数
    std::string  data_di;		//负荷记录di
}st_loadrec_block;
//负荷记录抄读参数
typedef struct LoadRecTask_Param{
    int64_t         dev_id;			    //设备ID
    int64_t         protocol_id;		//协议规则ID
    int             freeze_interval;    //冻结时间间隔(分钟)
    std::string     frozen_type;            //冻结数据类型
    std::list<st_loadrec_block>  lstdata_di;		//冻结数据DI列表
}st_dlt645_loadrec_param;

//冻结数据--单帧
typedef struct _frozen_single_frm_{
    uint8_t     *pfrozen_data;	//冻结数据
    int 		 data_len;		//冻结数据长度	
    _frozen_single_frm_(){
        pfrozen_data = nullptr;
        data_len = 0;
    }
}st_frozen_frmdata;

//冻结数据项
typedef struct _froken_data_item_{
    std::string      data_di;					//冻结数据DI 
    std::list<st_frozen_frmdata>  lstDataItem;   //冻结数据帧 
}st_frozen_dataitem;

//待解析冻结数据
typedef struct _dlt645_froken_rspdata_{
    int64_t 		dev_id;						//设备ID	
    int64_t 		rule_id;				    //协议规则ID
    std::string     frozen_type;				//冻结类型
    int64_t	 	    acq_start_time;				//采集开始时间
    int64_t	 	    acq_end_time;				//采集结束时间
    std::string     frozen_time_di;			    //冻结时间DI
    uint8_t         *pfroken_time_data;		    //冻结时间数据
    int 		    time_len;				    //冻结时间数据长度
    std::list<st_frozen_dataitem>   lstfrozenDatas;	//冻结数据集
    _dlt645_froken_rspdata_(){
        dev_id = 0;
        rule_id = 0;
        frozen_type = "";
        acq_start_time = 0;
        acq_end_time = 0;
        frozen_time_di = "";
        pfroken_time_data = nullptr;
        time_len = 0;
    }
}st_dlt645_frozen_rspdata;



#endif